<template>
	<div id="app">
		<!--游戏头部信息-->
		<game-header @resetStart="$refs.game.resetGame()"
		             @backStep="$refs.game.recoverBeforeMove()"/>
		<!--游戏主体内容-->
		<game-body ref="game"/>
		<!--游戏尾部提示-->
		<game-footer/>
		<!--移动端游戏界面-->
		<div class="swiper"></div>
		<!--游戏音效-->
		<audio class="music music-complex" src="~@/assets/music/tile-complex.mp3" preload="metadata"></audio>
		<audio class="music music-win" src="~@/assets/music/game-win.mp3" preload="metadata"></audio>
		<audio class="music music-lose" src="~@/assets/music/game-lose.mp3" preload="metadata"></audio>
	</div>
</template>

<script>
	import GameBody from "@/components/game/GameBody"
	import GameHeader from "@/components/game/GameHeader"
	import GameFooter from "@/components/game/GameFooter"

	import keyCode from "@/components/common/keycode"
	import debounce from "@/components/common/debounce"
	import Game from "@/game"

	export default {
		name: 'App',
		components: {
			GameBody,
			GameHeader,
			GameFooter
		},
		methods: {
			keyHandle(key_code) {
				/**
				 * 只有游戏为初始状态才会继续执行
				 */
				if (this.gameState !== 0) {
					return
				}
				/**
				 * 根据键码执行方法
				 */
				switch (key_code) {
					case keyCode.A:
					case keyCode.LEFT:
						this.$refs.game.gameLeft()
						break
					case keyCode.W:
					case keyCode.UP:
						this.$refs.game.gameTop()
						break
					case keyCode.D:
					case keyCode.RIGHT:
						this.$refs.game.gameRight()
						break
					case keyCode.S:
					case keyCode.DOWN:
						this.$refs.game.gameDown()
						break
				}
			},
			/**
			 * 计算滑动的方向
			 * 对手指滑动做处理
			 */
			touchHandle(ev, startX, startY) {
				/**
				 * 只有游戏为初始状态才会继续执行
				 */
				if (this.gameState !== 0) {
					return
				}
				let endX = ev.changedTouches[0].pageX
				let endY = ev.changedTouches[0].pageY
				/**
				 * 计算滑动与起始的差
				 */
				let x = endX - startX, y = endY - startY
				let absX = Math.abs(x)
				let absY = Math.abs(y)
				/**
				 * 开始判断
				 */
				if (absX > absY && x > 0) {
					this.$refs.game.gameRight()
				} else if (absX > absY && x < 0) {
					this.$refs.game.gameLeft()
				} else if (absY > absX && y > 0) {
					this.$refs.game.gameDown()
				} else if (absY > absX && y < 0) {
					this.$refs.game.gameTop()
				}
			},
			complexMusicHandle() {
				let musicComplex = document.querySelector('.music-complex')
				musicComplex.play()
			}
		},
		computed: {
			gameState() {
				return this.$store.state.winning
			}
		},
		mounted() {
			/**
			 * 防抖处理（立即执行）
			 */
			let handle = debounce(this.keyHandle, Game.WAIT_TIME)
			/**
			 * 监听键盘按下
			 * @param ev
			 */
			window.onkeydown = ev => {
				handle(ev.keyCode)
				ev.preventDefault()
			}
			/**
			 * 移动端监听手指滑动
			 */
			let [startX, startY] = [0, 0]
			/**
			 * 记录手指点击时的坐标
			 */
			window.addEventListener('touchstart', ev => {
				startX = ev.changedTouches[0].pageX
				startY = ev.changedTouches[0].pageY
			}, {passive: false})
			/**
			 * 滑动防抖（立即执行）
			 */
			let touchHandle = debounce(this.touchHandle, Game.TOUCH_WAIT_TIME)
			/**
			 * 手指离开屏幕的坐标
			 * 以计算手指滑动的方向
			 */
			window.addEventListener('touchend', ev => {
				touchHandle(ev, startX, startY)
			}, {passive: false})
			/**
			 * 阻止默认事件，让手指滑动时浏览器不滚动
			 * @type {Element}
			 */
			let swiper = document.querySelector('.swiper')
			swiper.addEventListener('touchstart', evt => evt.preventDefault())
			/**
			 * 游戏结束事件监听
			 */
			this.$bus.$on('gameWin', () => {
				this.$store.commit('win')
				let musicWin = document.querySelector('.music-win')
				musicWin.play()
			})
			this.$bus.$on('gameOver', () => {
				this.$store.commit('lose')
				let musicLose = document.querySelector('.music-lose')
				musicLose.play()
			})
			/**
			 * 监听页面刷新，保存数据
			 */
			window.addEventListener('beforeunload', this.$refs.game.save)
			/**
			 * 监听方块合成事件，做出动画音效
			 */
			let musicHandle = debounce(this.complexMusicHandle, Game.MOVE_ANIM_TIME)
			this.$bus.$on('complex', musicHandle)
			/**
			 * 监听玩家移动之前的事件
			 */
			this.$bus.$on('beforeMove', this.$refs.game.saveBeforeMove)
		}
	}
</script>

<style>
	body {
		background-color: #b7e8fe;
	}

	@media screen and (max-width: 520px) {
		body #app {
			width: 278px;
		}

		#app .reset-start {
			padding: 0;
			font-size: 14px;
			height: 30px;
			line-height: 30px;
		}

		#app .swiper {
			position: fixed;
			display: block;
			top: 0;
			bottom: 0;
			left: 0;
			right: 0;
		}
	}

	#app {
		font-family: Avenir, Helvetica, Arial, sans-serif;
		-webkit-font-smoothing: antialiased;
		-moz-osx-font-smoothing: grayscale;
		text-align: center;
		width: 500px;
		margin: 0 auto;
		font-size: 24px;
		color: #183178;
	}

	.reset-start {
		background-color: #183178;
		border-radius: 3px;
		padding: 0 20px;
		text-decoration: none;
		color: #f9f6f2;
		width: 100px;
		height: 40px;
		line-height: 42px;
		text-align: center;
		user-select: none;
		cursor: pointer;
	}

	.swiper {
		display: none;
	}

	.music {
		display: none;
	}
</style>
